<?php // $Id: sharpobj_data.php,v 1.18 2006/07/02 20:15:16 alex Exp $

// Подключаем базовые классы
mst_modfileload($MT_mod_name,'libs/sharpobj_data_base.php');

/**
 * Элемент данных
 *
 */
abstract class sharpobj_data_item extends sharpobj_data_baseitem implements sharpobj_data_interface_item
{
    /**
     * Тип объекта
     * Изменяется при переопределении
     *
     * @var string
     */    
    protected $type='undefined';
    /**
     * Проверенные данные
     *
     * @var mixed
     */
    private $t_data=null;
    /**
     * Значение по умолчанию
     *
     * @var mixed
     */
    private $default_data=null;
    /**
     * Нулевое значение
     *
     * @var mixed
     */
    private $null_data=null;
    /**
     * Исходные данные
     *
     * @var mixed
     */
    private $s_data=null;
    /**
     * Представление исходных данных
     *
     * @var string
     */
    private $s_view=null;
    /**
     * Дополнительные параметры
     * объекта
     *
     * @var array
     */
    private $options=null;

    /**
     * Флаг "состояние"
     * Доступ только через API
     * 
     * empty - значение не задано
     * null - значение null
     * default - значение по умолчанию
     * error - полученые данные не превильные
     * data - есть данные
     * @var string
     */
    private $flag_condition = 'empty';
    /**
     * Код ошибки фильра
     * Доступ только через API
     * 'unknown'
     * 'format'
     * 'vartype'
     * 'len'
     * 'value'
     * @var string
     */ 
    private $filter_error_code=null;
    /**
     * Является ли объект контейнером
     * 
     * @var string
     */
    protected $is_recurse =false;
    /**
     * Дополнительное описание ошибки
     * Доступ только через API
     * Значение зависит от типа ошибки
     * 
     * @var string
     */
    private $filter_error_opt=null;
    /**
     * Проверять ли входные данные на скалярность
     */
    protected $check_scalat = true;
    /**
     * Принудительно приводить к нужному типу данных
     */
    protected $set_vartype = false;

    // **********
    // Публичный интерфейс
    // **********
    /**
     * Получить данные из объекта
     *
     * @param string $view
     * @param string $datapath
     */
    function get($view,$datapath=null,$opt=null)
    {
        // Определяем имя функции
        $vfunc = "viewOut_{$view}";
        // Проверяем существование метода-фильтра
        if (!method_exists($this,$vfunc))
        {
            mst_error('Представление не существует',"В элементе {$this->type} отсутствует фильтр для представления'{$view}'",1);
            return false;            
        }
        if ($this->pathThis($datapath))
        {
            // Запускаем фильтр
            // Все проверки и установка данных производятся филтром
            // Фильтр возвращает данные
            $result = $this->$vfunc($opt);
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            $result = $this->subitemDo('get',$datapath,$view,null,$opt);
        }
        return $result;
        // 
    }
    /**
     * Сохранить данные в объект
     *
     * @param string $view
     * @param string $datapath
     * @param mixed $data
     */
    function set($view,$data=null,$datapath=null,$opt=null)
    {
        // Определяем имя функции
        $vfunc = "viewIn_{$view}";
        // Проверяем существование метода-фильтра
        if (!method_exists($this,$vfunc))
        {
            mst_error('Представление не существует',"В элементе {$this->type} отсутствует фильтр для представления'{$view}'",1);
            return false;
        }
        
        // Меняем состояние на "объект с данными"
        // Если это не так - в фильтрах будет переопределено
        $this->conditionData();
        
        if ($this->pathThis($datapath))
        {   // Сохраняем данные в текущем объекте
            // Сохраняем исходные данные
            $this->setSource($data);
            // Сохраняем представление исходных данных
            $this->setSourceView($view);
            // Запускаем фильтр
            // Все проверки и установка данных производятся фильтром
            // Фильтр возвращает true, если операция выполнена успешно
            $result = $this->$vfunc($opt);
        }else 
        {   // Обращаемся к вложенному объекту
            // Вызываем функцию обращения к вложенным элементам
            $result = $this->subitemDo('set',$datapath,$view,$data,$opt);
        }
        if (!$result AND !$this->isError())
        {   // Фильтр вернул отрицательный результат, но "забыл" установить ошибку
            // Устанавливаем ошибку неизвестного типа
            $this->conditionError('unknown');
        }
        // Возвращаем true, если все хорошо
        return !$this->isError();
    }
    /**
     * Получить данные из объекта в представлении plain
     *
     * @param string $view
     * @param string $datapath
     */
    function getP($datapath=null,$opt=null)
    {
        return $this->get('plain',$datapath,$opt);
    }
    /**
     * Сохранить данные в объект из представления plain
     *
     * @param string $datapath
     * @param mixed $data
     */
    function setP($data=null,$datapath=null,$opt=null)
    {
        $res = $this->set('plain',$data,$datapath,$opt);
        /*
        // Больше не ругаемся, поскольку false при неправильных исходных данных - штатная ситуация
        if ($res === false)
        {
            mst_error('Ошибка установки данных в объект',"Операция вставки данных в стандартном представлении завершилась с ошибкой",1);
        }
		*/
        return $res;
    }
    
    /**
     * Очистить данные
     *
     * @param string $datapath
     */
    function clear($datapath=null)
    {
        if ($this->pathThis($datapath))
        {
            // Очищаем текущий объект
            $this->conditionEmpty();
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            $result = $this->subitemDo('clear',$datapath);
        }
    }

     /**
     * Вернуть тип объекта
     *
     * @param string $datapath
     */
    function type($datapath=null)
    {
        if ($this->pathThis($datapath))
        {
            // Возвращаем тип текущего объекта
            return $this->type;
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            return $this->subitemDo('type',$datapath);
        }
    }    
    // **********
    // Методы управления состояниями
    // **********
        
    protected function conditionEmpty()
    {
        $this->flag_condition='empty';
        $this->clearAttributsAll();
    }
    protected function conditionNull()
    {
        $this->flag_condition='null';
        $this->clearAttributsAll();
    }
    protected function conditionError($error_code=null,$error_opt=null)
    {
        $this->flag_condition='error';
        $this->filter_error_code = $error_code;
        $this->filter_error_opt = $error_opt;
    }
    protected function conditionDefault()
    {
        $this->flag_condition='default';
        // Очищаем существующие атрибуты
        $this->clearAttributsAll();
    }
    protected function conditionData()
    {
        $this->flag_condition='data';
    }
    
    protected function getCondition()
    {
        // Получить состояние объекта
        // Для проверки состояний объекта пользователем
        // используйте функции проверки состояний
        // Для внешней проверки используйте функции isXXX
        return $this->flag_condition;
    }

    /**
     * Существует ли элемент
     *
     * @param string $datapath
     * @return bool
     */
    function isExists($datapath=null)
    {
        // Была ли ошибка в формате
        if ($this->pathThis($datapath))
        {
            return true;
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            return $this->subitemDo('isExists',$datapath);
        }

    }
    
    /**
     * Состояние элемента - error?
     *
     * @param string $datapath
     * @return bool
     */
    function isError($datapath=null)
    {
        // Была ли ошибка в формате
        if ($this->pathThis($datapath))
        {
            return $this->getCondition()=='error';
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            return $this->subitemDo('isError',$datapath);
        }

    }
    /**
     * Состояние элемента null?
     *
     * @param string $datapath
     * @return bool
     */
    function isNull($datapath=null)
    {
        // Содержит ли объект null
        if ($this->pathThis($datapath))
        {
            return $this->getCondition()=='null';
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            return $this->subitemDo('isNull',$datapath);
        }
        
    }
    /**
     * Элемент пуст?
     *
     * @param string $datapath
     * @return bool
     */
    function isEmpty($datapath=null)
    {
        // Пуст ли объект
        if ($this->pathThis($datapath))
        {
            return ($this->getCondition()=='empty') OR ($this->getCondition()=='error');
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            return $this->subitemDo('isEmpty',$datapath);
        }
    }
    /**
     * Элемент содержит значение по умолчанию?
     *
     * @param string $datapath
     * @return bool
     */
    function isDefault($datapath=null)
    {
        // Пуст ли объект
        if ($this->pathThis($datapath))
        {
            return $this->getCondition()=='default';
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            return $this->subitemDo('isDefault',$datapath);
        }
        
    }
    /**
     * Элемент не содержит данных?
     *
     * @param string $datapath
     * @return bool
     */
    function isNoData($datapath=null)
    {
        // Содержит ли объект null или empty
        if ($this->pathThis($datapath))
        {
            return ($this->getCondition()=='empty') OR ($this->getCondition()=='null')
                OR ($this->getCondition()=='error');
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            return $this->subitemDo('isNoData',$datapath);
        }
        
    }
    /**
     * Элемент содержит данные?
     *
     * @param string $datapath
     * @return bool
     */
    function isData($datapath=null)
    {
        // Содержит ли объект данные, отличные от Empty и Null
        if ($this->pathThis($datapath))
        {
            return ($this->getCondition()=='data') OR ($this->getCondition()=='default');
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            return $this->subitemDo('isData',$datapath);
        }
    }
    function getErrorCode()
    {
        return $this->filter_error_code;
    }
    function getErrorOpt()
    {
        return $this->filter_error_opt;
    }
    function getErrorText()
    {
        return sharpobj_errorcode2text($this->getErrorCode(),$this->getErrorOpt());
    }
    // **********
    // Служебные функции
    // **********
    protected  function readData()
    {   // Получить данные из объекта
        
        if ($this->isNoData())
        {   // Нулевое значение
            $result = $this->getNullValue();
        }elseif ($this->isDefault())
        {   // Значение по умолчанию
            $result = $this->getDefaultValue();
        }else 
        {   // Данные
            $result = $this->t_data;
        }
        
        return $result;
    }
    protected  function saveData($data)
    {   // Сохранить в объекте проверенные данные, приведенные к внутреннему формату
        $data = $this->viewMiscVartype($data);
        $this->t_data = $data;
        return true;
    }
    function getDefaultValue()
    {   // Получить значение по умолчанию для элемента
        return $this->default_data;
    }
    function setDefaultValue($data)
    {   // Установить значение по умолчанию для элемента
        // $data - значение по умолчанию во внутреннем формате объекта
        $this->default_data = $data;
    }
    function getNullValue()
    {   // Получить нулевое значение для элемента
        return $this->null_data;
    }
    function setNullValue($data)
    {   // Установить нулевое значение для элемента
        // $data - нулевое значение во внутреннем формате объекта
        $this->null_data = $data;
    }
    protected function getSource()
    {   // Получить исходные данные
        return $this->s_data;
    }
    protected function setSource($data)
    {   // Установить исходные данные
        $this->s_data = $data;
    }
    protected function getSourceView()
    {   // Получить представление исходных данных
        return $this->s_view;
    }
    protected function setSourceView($view)
    {   // Установить представление исходных данных
        $this->s_view = $view;
    }
    function getOption($name)
    {   // Получить значение опции формата
        return @$this->options[$name];
    }
    function setOption($name,$value)
    {   // Установить значение опции формата
        $this->options[$name]=$value;
    }
    function unsetOption($name)
    {   // Удалить переменную опции формата
        unset($this->options[$name]);
    }
    function isOptionSet($name)
    {   // Установленга ли переменная опции формата
        return isset($this->options[$name]);
    }
    /**
     * Очистить все атрибуты, содержащие данные
     *
     * @param unknown_type $datapath
     */
    protected  function clearAttributsAll($datapath=null)
    {
        if ($this->pathThis($datapath))
        {
            // Действие обращено к текущему объекту
            $this->clearAttributsData($datapath);
            // Представение исходных данных не определено
            $this->s_view = null;
            // Текст ошибки фильтра не задан
            $this->filter_error_text = null;
            // Код ошибки филтра не задан
            $this->filter_error_code = null;
            
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            $result = $this->subitemDo('clear',$datapath);
        }
    }
    /**
     * Очистить атрибуты, содержащие данные
     *
     * @param unknown_type $datapath
     */
    protected  function clearAttributsData($datapath=null)
    {
        if ($this->pathThis($datapath))
        {
            // Действие обращено к текущему объекту
            // Проверенных данных нет
            $this->t_data = null;
            // Исходных данных нет
            $this->s_data = null;
        }else 
        {
            // Вызываем функцию обращения к вложенным элементам
            $result = $this->subitemDo('clear',$datapath);
        }
    }
    /**
     * Выполнить действие с вложенными элементами
     * должна быть переопределена для класса, поддерживающего вложенность
     *
     * @param string $do
     * @param string $datapath
     * @param string $view
     * @param mixed $data
     */
    protected  function subitemDo($do,$datapath,$view=null,$data=null,$opt=null)
    {
        mst_error('Обращение к вложенному элементу',"Элементы {$this->type} не поддерживают вложенность",2);
    }

    /**
     * Enter description here...
     *
     * @param unknown_type $datapath
     */
    // abstract  function  setNull($datapath);

/*
    function addSubItem($type,$param=null,$source=null)
    {
    }
*/
    function __construct($options=null)
    {
        if (!is_null($options))
        {
            $this->options = $options;
            if (isset($options['default']))
            {
                // Устанавливаем значение по умолчанию
                $this->setDefaultValue($options['default']);
            }
            if (isset($options['nullvalue']))
            {
                // Устанавливаем нулевое значение
                $this->setNullValue($options['nullvalue']);
            }
            if (isset($options['empty2null']) AND !isset($options['formempty2null']))
            {
                // Преобразуем старую версию атрибута к новой
                $this->options['formempty2null'] = $options['empty2null'];
  
            }
            if (isset($options['formempty2null']) AND !$this->options['formempty2null'])
            {
              // По умолчанию пустые поля в формах преобразуются в Null
                $this->options['formempty2null']=true;
            }
            if (isset($options['null_error']) AND !isset($options['null']))
            {
                // Преобразуем старую версию атрибута к новой
                $this->options['null'] = !$options['null_error'];
  
            }
        }
    }
    
    // **********
    // Фильтры
    // **********
    
    // Служебные функции, используемые в фильтрах
    /**
     * Убрать магические слеши, если они добавлялись в момент запуска
     *
     * @param string $str
     * @return string
     */
    protected  function viewMiscStripslashesGPC($str)
    {
        if (get_magic_quotes_gpc())
        {
            $str = stripslashes($str);
        }
        return $str;
    }
    /**
     * Убрать магические слеши, если они добавлялись после запуска при работе с файлами и т.д.
     *
     * @param string $str
     * @return string
     */
    protected  function viewMiscStripslashesRuntime($str)
    {
        if (get_magic_quotes_runtime())
        {
            $str = stripslashes($str);
        }
        return $str;
    }
    protected  function viewMiscTrim($data,$opt=null)
    {
        if ($this->getOption('trim') and is_string($data))
        {
            $data = trim($data);
        }
        return $data;
    }
    protected  function viewMiscFilter($data,$opt=null)
    {
        // Преобразуем входящий элемент
        // Для использования, функция должна быть переопределена в дочернем классе
        // Здесь не допускается выполнять никаких значимых преобразований, могущих нарушить
        // исходное значение данных, так как преобразование выполняется без предупреждения
        return $data;
    }
    /**
     * Принудительно установить тип данных 
     * (вызывать только после всех проверок, иначе данные будут потеряны без предупреждения)
     */
    protected  function viewMiscVartype($data)
    {
        if ($this->set_vartype !==false)
        {
            settype($data,$this->set_vartype);
        }
        return $data;
    }
    
    // Проверки
    
    protected  function viewMiscCheckNullValue($data)
    {   // Проверяем на null и устанавливаем состояние элемента
        if (is_null($data))
        {   //
            // Объект содержит null 
            $this->conditionNull();
            return true;
        }
        return false;
    }
    /**
     * Проверить длину строки и установить состояние объекта (при ошибке возвращает true)
     *
     * @param string $str
     * @return bool
     */
    protected  function viewMiscCheckLenError($str)
    {
        $len = strlen($str);
        if (($len > $this->getOption('len_max')) AND $this->isOptionSet('len_max'))
        {
            $this->conditionError('len','max');
            return true;
        }
        if (($len < $this->getOption('len_min')) AND $this->isOptionSet('len_min'))
        {
            $this->conditionError('len','min');
            return true;
        }
        return false;
    }
    protected  function viewMiscCheckNullError($data,$opt=null)
    {   // Проверяем входное значение на null, если он запрещен в настройках
        if (is_null($data) 
                AND ($this->isOptionSet('null') AND $this->getOption('null')===false)
                    
            )
        {
            $this->conditionError('value','null');
            return true;
        }
        return false;
    }
    protected  function viewMiscCheckFormatError($data,$opt=null)
    {   // Пользовательский фильтр формата данных
        // Если ошибка - возвращаем true
        // Для установки проверки должен быть переопределен
        if (true)
        {   // Все хорошо
            return false;
        }else 
        {
            $this->conditionError('format');
            return true;
        }
    }
    protected  function viewMiscCheckValueError($data,$opt=null)
    {   // Пользовательский фильтр целостности данных
        // Если ошибка - возвращаем true
        // Для установки проверки должен быть переопределен
        if (true)
        {   // Все хорошо
            return false;
        }else 
        {
            $this->conditionError('value');
            return true;
        }
    }
    protected  function viewMiscCheckScalarError($data)
    {   //  Проверка
        // Если ошибка - возвращаем true
        // Для установки проверки должен быть переопределен
        if ($this->check_scalat AND (is_null($data) OR is_scalar($data)))
        {   // Все хорошо
            return false;
        }else 
        {
            $this->conditionError('vartype',gettype($data));
            return true;
        }
    }

    
    // Объявляем фильтры представлений   
    // "простой вид" - данные как есть
    function viewIn_plain($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        // Получаем исходные данные
        $data = $this->getSource();
        
        if ($this->viewMiscCheckScalarError($data))
        {
            return false;
        }
        if ($this->viewMiscCheckNullError($data))
        {   // Объект содержит null и ноль запрещен
            return false;
        }
        if ($this->viewMiscCheckNullValue($data))
        {   // Объект содержит null
            return true;
        }
        
        // Удаляем незначащие пробелы, если разрешено
        $data = $this->viewMiscTrim($data);
        $data = $this->viewMiscFilter($data);
        if ($this->viewMiscCheckLenError($data))
        {   // Неправильный размер данных
            return false;
        }
        if ($this->viewMiscCheckFormatError($data))
        {   // Формат значения элемента неправильный
            return false;
        }
        if ($this->viewMiscCheckValueError($data))
        {   // Значение объекта не правильное
            return false;
        }
        // Меняем состояние на "объект с данными"
        $this->saveData($data);
        $this->conditionData();
        return true;
    }
    function viewOut_plain($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        return $this->readData();
    }
    
    // "значение по умолчанию" - привести данные к значениям по умолчанию
    function viewIn_default($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        $this->conditionDefault();
        return true;
    }
    
    // "формы" - работа с данными из форм
    function viewIn_form($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        // Получаем исходные данные
        $data = $this->getSource();

        if ($this->viewMiscCheckScalarError($data))
        {
            return false;
        }
        if (empty($data) and 
                ($this->isOptionSet('formempty2null') AND $this->getOption('formempty2null'))
                
            )
        {
            $data = null;
        }
        if ($this->viewMiscCheckNullError($data))
        {   // Объект содержит null и ноль запрещен
            return false;
        }
        if ($this->viewMiscCheckNullValue($data))
        {   // Объект содержит null
            return true;
        }

        // Удаляем незначащие пробелы, если разрешено
        $data = $this->viewMiscTrim($data);
        $data = $this->viewMiscFilter($data);
        
        // Удаляем магические кавычки
        $data = $this->viewMiscStripslashesGPC($data);
        
        if ($this->viewMiscCheckLenError($data))
        {   // Неправильный размер данных
            return false;
        }

        if ($this->viewMiscCheckFormatError($data))
        {   // Формат значения элемента неправильный
            return false;
        }
        if ($this->viewMiscCheckValueError($data))
        {   // Значение объекта не правильное
            return false;
        }

        // Меняем состояние на "объект с данными"
        $this->saveData($data);
        $this->conditionData();
        return true;
    }
    function viewOut_form($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        // Возвращаем данные, обработанные для отображения в форме
        return htmlspecialchars($this->readData());
    }
    // Отображение на html-странице
    function viewOut_html($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        // Возвращаем данные, обработанные для отображения в форме
        return htmlspecialchars($this->readData());
    }
    // "базы данных" - работа с данными из БД
    function viewIn_sql($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        // Получаем исходные данные
        $data = $this->getSource();

        if ($this->viewMiscCheckScalarError($data))
        {
            return false;
        }
        if ($this->viewMiscCheckNullError($data))
        {   // Объект содержит null и ноль запрещен
            return false;
        }
        if ($this->viewMiscCheckNullValue($data))
        {   // Объект содержит null
            return true;
        }
        
        // Удаляем незначащие пробелы, если разрешено
        $data = $this->viewMiscTrim($data);
        $data = $this->viewMiscFilter($data);

        // Удаляем магические кавычки
        $data = $this->viewMiscStripslashesRuntime($data);
        
        if ($this->viewMiscCheckLenError($data))
        {   // Неправильный размер данных
            return false;
        }

        if ($this->viewMiscCheckFormatError($data))
        {   // Формат значения элемента неправильный
            return false;
        }
        if ($this->viewMiscCheckValueError($data))
        {   // Значение объекта не правильное
            return false;
        }
        // Меняем состояние на "объект с данными"
        $this->saveData($data);
        $this->conditionData();
        return true;
    }
    function viewOut_sql($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        // Возвращаем данные, обработанные для отображения в форме
        // if (is_null($this->readData()))
        if ($this->isNull())
		{
			return null;
		}else
		{
			return addslashes($this->readData());
		}
        
    }
    function viewOut_validate($opt=null)
    {
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        // Возвращаем состояния текущих проверок
        if ($this->isError())
        {
            return array(
                        'error'=>true,
                        'error_code'=>$this->getErrorCode(),
                        'error_opt'=>$this->getErrorOpt(),
                        'source'=>$this->getSource(),
                        'source_view'=>$this->getSourceView(),
            			'error_text'=>$this->getErrorText()
                        );
        
        }else 
        {
            return false;
        }
    }
    
    /**
     * Вернуть данные в виде плоского массива (для mysql_flex)
     * @param array $opt - параметры обработки
     * @return array
     */
    function viewOut_rdata($opt=null)
    {
    	// Представление, в котором выбираются данные
    	if (!isset($opt['view'])){$opt['view']='sql';}
    	// Добавлять ли в массив информацию о пустых элементах
        if (!isset($opt['noempty'])){$opt['noempty']=true;}
        // Нужны ли значения?
        if (!isset($opt['novalue'])){$opt['novalue']=false;}
        if ($this->is_recurse)
        {
            mst_error('Рекурсия не поддерживается',
                "Для поддержки рекурсии метод ".__FUNCTION__." класса ".get_class($this)." должен быть переопределен",2);
        }
        $res = array('type'=>htmlspecialchars($this->type()));
        if (false === $opt['novalue'])
        {
        	$res['value'] = $this->get($opt['view']);
        	if ($opt['view']==='sql' AND $this->isNull())
			{
				// Обрабатываем значения NULL
				$res['value'] = 'Null';
			}elseif($opt['view']==='sql')
			{
				$res['value'] = "'{$res['value']}'";
			}
		}
        // Возвращаем состояния текущих проверок
        return $res;
    }
    
}


// Создаем производные классы элементов данных
mst_modfileload($MT_mod_name,'libs/datatype/double.php');
mst_modfileload($MT_mod_name,'libs/datatype/email.php');
mst_modfileload($MT_mod_name,'libs/datatype/int.php');
mst_modfileload($MT_mod_name,'libs/datatype/path.php');
mst_modfileload($MT_mod_name,'libs/datatype/row.php');
mst_modfileload($MT_mod_name,'libs/datatype/smallatword.php');
mst_modfileload($MT_mod_name,'libs/datatype/string.php');
mst_modfileload($MT_mod_name,'libs/datatype/text.php');
mst_modfileload($MT_mod_name,'libs/datatype/html.php');
mst_modfileload($MT_mod_name,'libs/datatype/url.php');
mst_modfileload($MT_mod_name,'libs/datatype/phone.php');
mst_modfileload($MT_mod_name,'libs/datatype/data.php');
mst_modfileload($MT_mod_name,'libs/datatype/array.php');
mst_modfileload($MT_mod_name,'libs/datatype/error.php');

?>